import asyncio
import heapq
import time
from typing import Dict, Optional

"""_summary_
我现在要实现这样一个延迟任务管理DelayManager类，要求：
1. 同一时间一个game_id下只能存在一个延迟任务
2. 当延迟任务的计时器超时后，会调用回调函数，并删除该任务计时。
3. 可以手动取消一个任务计时。
4. 可以获取某个game_id下的当前任务距离触发还有多久。
"""

class TimerInfo:
    def __init__(self, game_id: str, when: float, task: asyncio.Task, phase_info: dict):
        self.game_id = game_id
        self.when = when
        self.task = task
        self.phase = phase_info
        
    def get_left_time(self) -> int:
        """获取剩余时间"""
        return int(self.when - time.time())

class DelayManager:
    def __init__(self):
        # self._queue = []
        self._timers: Dict[str, TimerInfo] = {}
        self._locks: Dict[str, asyncio.Lock] = {}
        self._lock = asyncio.Lock()
    
    async def start_timer(self, game_id: str, duration: float, phase_info: dict, callback):
        """启动或重置计时器"""
        if game_id not in self._locks:
            async with self._lock:
                self._locks[game_id] = asyncio.Lock()
        # 取消已有的计时器（如果存在）
        await self._cancel_existing_timer(game_id)
        
        # 创建新计时器
        when = time.time() + duration
        timer_task = asyncio.create_task(self._run_timer(when, game_id, callback))
        timer_info = TimerInfo(game_id, when, timer_task, phase_info)
        self._timers[game_id] = timer_info
    
    async def restart_timer(self, game_id: str, duration: float, callback):
        """重置现有计时器"""
        time_info = self._timers[game_id]
        await self.start_timer(game_id, duration, time_info.phase, callback)
    
    async def _cancel_existing_timer(self, game_id: str):
        """取消已有的计时器"""
        if game_id in self._timers:
            task = self._timers[game_id].task
            task.cancel()
            try:
                await task
            except asyncio.CancelledError:
                pass
            del self._timers[game_id]
    
    async def _run_timer(self, when: float, game_id: str, callback):
        """实际执行计时器逻辑"""
        try:
            delay = when - time.time()
            if delay > 0:
                await asyncio.sleep(delay)
            
            # 确保这是当前活跃的计时器（没有被重置）
            if game_id in self._timers and self._timers[game_id].task == asyncio.current_task():
                print(f"延迟任务 {game_id} 执行")
                await callback(game_id)
        except asyncio.CancelledError:
            pass
    
    async def cancel_timer(self, game_id: str):
        """手动取消计时器"""
        await self._cancel_existing_timer(game_id)

    def get_game_lock(self, game_id: str):
        if game_id not in self._locks:
            self._locks[game_id] = asyncio.Lock()
        return self._locks[game_id]
    
    async def stop_game(self, game_id: str):
        """对局结束，释放锁"""
        async with self._lock:
            if game_id in self._locks:
                del self._locks[game_id]
                
    
    def get_left_time_by_game_id(self, game_id: str) -> Optional[int]:
        """获取指定游戏 ID 的延迟任务的剩余时间"""
        if game_id in self._timers:
            return self._timers[game_id].get_left_time()
        return 0

delay_manager = DelayManager()